package com.yc.tomcat.core;

import java.io.BufferedReader;	
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.yc.tomcat.utils.StringUtil;

public class HttpServletRequest implements ServletRequest{
	private String method;
	private String url;
	private String protocal;
	private Map<String, String> parameters = new Hashtable<String, String>(); // 存储请求中的参数
	private InputStream is;
	private BufferedReader reader = null;
	
	// TODO cookie session
	private Cookie[] cookies;
	private String jsessionId = null;
	
	public HttpServletRequest(InputStream is) {
		this.is = is;
		parse();
	}

	
	@Override
	public void parse() {
		try {
			reader = new BufferedReader(new InputStreamReader(is));
			String line = null;
			List<String> headers = new ArrayList<String>();
			while ((line = reader.readLine()) != null && !"".equals(line)) {
				headers.add(line);
			}
			
			// headers.forEach(System.out::println);
			// 解析起始行
			parseFirstLine(headers.get(0));
			
			/*parameters.forEach((key, val) -> {
				System.out.println(key + " : " + val); 
			});*/
			
			// 解析参数
			parseParameter(headers);
			
			// TODO 处理cookie
			parseCookies(headers);
			
			//System.out.println(Arrays.toString(cookies));
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 解析处理cookie
	 * @param headers
	 */
	private void parseCookies(List<String> headers) {
		String cookieStr = null;
		for (String str : headers) {
			if (str.contains(ContantInfo.REQUEST_COOKIE)) {
				cookieStr = str;
				break;
			}
		}
		
		if (!StringUtil.checkNull(cookieStr)) {  // 说明有cookie信息
			cookieStr = cookieStr.substring(cookieStr.indexOf(":") + 1);
			String[] cookiess = cookieStr.split("; ");  // 分割每一个cookie
			cookies = new Cookie[cookiess.length];
			String[] ck = null;
			Cookie cookie = null;
			for (int i = 0, len = cookiess.length; i < len; i ++) {
				ck = cookiess[i].split("=");
				if (ck.length > 1) {
					cookie = new Cookie(ck[0].trim(), ck[1].trim());
				} else {
					cookie = new Cookie(ck[0].trim(), "");
				}
				cookies[i] = cookie;
			}
			
			// 获取解析JessionId
			parseJessionId();
		}
	}

	/**
	 * 处理jsessionId
	 */
	private void parseJessionId() {
		if (cookies != null && cookies.length >= 0) {
			for (int i = 0, len = cookies.length; i < len; ++ i) {
				// 如果有jsessionId，说明不是一次新的对话，则先获取jsessionId
				if (cookies[i].getName().contentEquals(ContantInfo.REQUEST_JSESSIONID)) {
					jsessionId = cookies[i].getValue();  // 获取jsessionId
					
					// 更新session的过期时间，即更新session的最后访问时间
					ClearSession.clearMap.put(jsessionId, new Date());
				}
			}
		}
		
	}

	/**
	 * 解析起始行
	 * @param str
	 */
	private void parseFirstLine(String str) {
		if (StringUtil.checkNull(str)) {
			return;
		}
		
		String[] arrs = str.split(" ");  // 根据空格分割
		this.method = arrs[0];
		this.protocal = arrs[2];
		
		if (arrs[1].contains("?")) {  // 说明请求地址中带有参数
			this.url = arrs[1].substring(0, arrs[1].indexOf("?"));
			
			try {
				// 处理请求参数
				String parameterStr = arrs[1].substring(arrs[1].indexOf("?") + 1);
				parameterStr = URLDecoder.decode(parameterStr, "utf-8"); // 转码
				getParam(parameterStr);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			return;
		}
		
		this.url = arrs[1];
	}

	/**
	 * 处理请求参数
	 * @param parameterStr
	 */
	private void getParam(String parameterStr) {  // account=yc&pwd=123
		String[] params = parameterStr.split("&");
		if (params != null && params.length > 0) {
			String[] temp = null;
			for (String param : params) {
				temp = param.split("=");
				if (temp.length == 1) {
					this.parameters.put(temp[0].trim(), "");
					continue;
				}
				this.parameters.put(temp[0].trim(), temp[1].trim());
			}
		}
	}
	
	/**
	 * 解析参数的
	 * @param headers
	 */
	private void parseParameter(List<String> headers) {
		if (ContantInfo.REQUEST_METHOD_POST.equals(method)) {  // post请求
			
			// 先将首部字段中的请求的数据长度Content-Length
			int len = 0;
			for (String head : headers) {
				if (head.contains("Content-Length:")) {
					len = Integer.parseInt(head.substring(head.indexOf(":") + 1).trim());
					break;
				}
			}
			
			// 如果后面以后数据过来，再获取数据的类型Content-Type
			boolean checkStr = true;
			for (String head : headers) {
				if (head.contains("Content-Type:")) {
					if (head.contains("multipart/form-data")) {
						checkStr = false;
						break;
					}
				}
			}
			
			if (len <= 0) {  // 说明后面没有数据
				return;
			}
			
			if (checkStr) {  // 说明后面是普通文本数据
				try {
//					System.out.println("post");
					char[] ch = new char[1024];
					int count = 0, total = 0;
					StringBuffer sbf = new StringBuffer();
					// 循环读取数据
					while ((count = reader.read(ch)) > 0) {
						sbf.append(ch, 0, count);
						total += count;
						if (total >= len) {
							break;
						}
					}
					String str = URLDecoder.decode(sbf.toString(), "utf-8");
					getParam(str);
				} catch (IOException e) {
					e.printStackTrace();
				}
				return;
			}
			
			// TODO 流数据
		}
	}
	
	@Override
	public String getParameter(String key) {
		return parameters.get(key);
	}

	@Override
	public String getMethod() {
		return this.method;
	}

	@Override
	public String getUrl() {
		return this.url;
	}

	@Override
	public String getProtocal() {
		return this.protocal;
	}


	@Override
	public Cookie[] getCookie() {
		return cookies;
	}


	@Override
	public Session getSession() {
		// 如果cookie中有jessionId并且sessions中的jessionId没有过期
		if (!StringUtil.checkNull(jsessionId) && TomcatServer.sessions.containsKey(jsessionId)) {
			return TomcatServer.sessions.get(jsessionId);
		}
		
		// 如果没有则认为是一次新的会话，需要创建一个jsessionId存到客户端的cookie中
		jsessionId = UUID.randomUUID().toString();
		
		// 创建session对象
		Session session = new HttpSession();
		session.setId(jsessionId);
		
		// 存到tomcat的总session中
		TomcatServer.sessions.put(jsessionId, session);
		
		// 将这个session添加到session过期清空列表中
		ClearSession.clearMap.put(jsessionId, new Date());
		
		ServerService.jsessionId = jsessionId;
		return session;
	}

}
